package utils

import (
	"bufio"
	"encoding/binary"
	"encoding/json"
	"io"
	"net"
	"sync"
)

const (
	headerSize = 4 // 4字节长度前缀
)

type JSONEncoder struct {
	conn   net.Conn
	writer *bufio.Writer
	mutex  sync.Mutex
}

func NewJSONEncoder(conn net.Conn) *JSONEncoder {
	return &JSONEncoder{
		conn:   conn,
		writer: bufio.NewWriter(conn),
	}
}

func (je *JSONEncoder) Encode(v interface{}) error {
	je.mutex.Lock()
	defer je.mutex.Unlock()

	data, err := json.Marshal(v)
	if err != nil {
		return err
	}

	// 写入长度前缀
	header := make([]byte, headerSize)
	binary.BigEndian.PutUint32(header, uint32(len(data)))

	// 写入头信息
	if _, err := je.writer.Write(header); err != nil {
		return err
	}

	// 写入实际数据
	if _, err := je.writer.Write(data); err != nil {
		return err
	}

	return je.writer.Flush()
}

type JSONDecoder struct {
	conn   net.Conn
	reader *bufio.Reader
	mutex  sync.Mutex
}

func NewJSONDecoder(conn net.Conn) *JSONDecoder {
	return &JSONDecoder{
		conn:   conn,
		reader: bufio.NewReader(conn),
	}
}

func (jd *JSONDecoder) Decode(v interface{}) error {
	jd.mutex.Lock()
	defer jd.mutex.Unlock()

	// 读取长度前缀
	header := make([]byte, headerSize)
	if _, err := io.ReadFull(jd.reader, header); err != nil {
		return err
	}

	// 解析数据长度
	dataLen := binary.BigEndian.Uint32(header)
	if dataLen == 0 {
		return io.EOF
	}

	// 读取实际数据
	data := make([]byte, dataLen)
	if _, err := io.ReadFull(jd.reader, data); err != nil {
		return err
	}

	return json.Unmarshal(data, v)
}
